package com.smallstep.hystrix.entity;

import com.netflix.hystrix.*;
import com.netflix.hystrix.HystrixCommand.Setter;
import com.netflix.hystrix.HystrixCommandGroupKey.Factory;
import com.smallstep.hystrix.enums.ReturnModeEnum;
import com.smallstep.hystrix.utils.UrlUtil;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;

import java.lang.reflect.Type;
import java.net.URL;
import java.util.Map;

/**
 * @author 李俊
 */
public class FFRequestInfo extends FFRequestKey {

    private String url;
    private ReturnModeEnum returnMode;
    private HttpEntity<?> requestEntity;
    private Map<String, ?> uriVariablesMap;
    private Object[] uriVariables;

    public Setter toHystrixSetting(FFFallbackMethod fallbackMethod) {
        Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(this.service))
                .andCommandKey(HystrixCommandKey.Factory.asKey(this.method + "$" + this.service + this.path))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(this.service));
        if (fallbackMethod.isCircuitBreakerEnabled()) {
            setter.andThreadPoolPropertiesDefaults(	// 配置线程池
                    HystrixThreadPoolProperties.Setter()
                            .withCoreSize(200)	// 配置线程池里的线程数，设置足够多线程，以防未熔断却打满threadpool
            ).andCommandPropertiesDefaults(
                    HystrixCommandProperties.Setter()
                            .withCircuitBreakerEnabled(true)
                            .withCircuitBreakerRequestVolumeThreshold(fallbackMethod.getCircuitBreakerRequestVolumeThreshold())
                            .withCircuitBreakerErrorThresholdPercentage(fallbackMethod.getCircuitBreakerErrorThresholdPercentage())
                            .withCircuitBreakerSleepWindowInMilliseconds(fallbackMethod.getCircuitBreakerSleepWindowInMilliseconds())
            );
        }
        return setter;
    }


    public FFRequestInfo(ReturnModeEnum returnMode, String urlStr, HttpMethod method, HttpEntity<?> requestEntity, Type responseType, Map<String, ?> uriVariablesMap) {
        this(returnMode, urlStr, method, requestEntity, responseType);
        this.uriVariablesMap = uriVariablesMap;
    }

    public FFRequestInfo(ReturnModeEnum returnMode, String urlStr, HttpMethod method, HttpEntity<?> requestEntity, Type responseType, Object... uriVariables) {
        this(returnMode, urlStr, method, requestEntity, responseType);
        this.uriVariables = uriVariables;
    }

    public FFRequestInfo(ReturnModeEnum returnMode, String urlStr, HttpMethod method, HttpEntity<?> requestEntity, Type responseType) {
        try {
            this.url = urlStr;
            this.method = method;
            this.returnMode = returnMode;
            this.requestEntity = requestEntity;
            if (responseType == null) {
                this.responseType = Void.TYPE;
            } else {
                this.responseType = responseType;
            }

            URL url = UrlUtil.format(urlStr);
            this.service = UrlUtil.getHost(url);
            this.path = url.getPath();
        } catch (Exception var7) {

        }

    }

    public FFRequestKey toFFRequestKey() {
        return new FFRequestKey(this.service, this.path, this.method, this.responseType);
    }



    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public ReturnModeEnum getReturnMode() {
        return returnMode;
    }

    public void setReturnMode(ReturnModeEnum returnMode) {
        this.returnMode = returnMode;
    }

    public HttpEntity<?> getRequestEntity() {
        return requestEntity;
    }

    public void setRequestEntity(HttpEntity<?> requestEntity) {
        this.requestEntity = requestEntity;
    }

    public Map<String, ?> getUriVariablesMap() {
        return uriVariablesMap;
    }

    public void setUriVariablesMap(Map<String, ?> uriVariablesMap) {
        this.uriVariablesMap = uriVariablesMap;
    }

    public Object[] getUriVariables() {
        return uriVariables;
    }

    public void setUriVariables(Object[] uriVariables) {
        this.uriVariables = uriVariables;
    }
}
